package application;

import game.GameModel;
import gui.GUIFacade;

import java.util.Date;
import java.util.List;

import javax.swing.ImageIcon;
import javax.swing.JMenu;
import javax.swing.JPanel;

import technicalservices.error.ErrorHandler;
import domain.advertisement.Ad;
import domain.advertisement.AdvertisementScheme;
import domain.tournament.ITournament;
import domain.users.User;

/**
 * ArenaManager is the central part of the system. The ArenaManager knows about
 * all the controller within the system; likewise the controllers know about the
 * ArenaManager. The communication between controllers goes trough the
 * ArenaManager.
 * 
 * Design pattern: Facade, Singleton
 */
public class ArenaManager {

	// Instance:
	private static ArenaManager instance;
	// Controllers:
	private GUIFacade guiFacade;
	private AdController adController;
	private UserController userController;
	private LeagueController leagueController;
	private OperatorController operatorController;

	private ArenaManager() {
		guiFacade = new GUIFacade();
		adController = new AdController();
		userController = new UserController();
		leagueController = new LeagueController();
		operatorController = new OperatorController();
	}

	public static ArenaManager getInstance() {
		if (instance == null) 
			instance = new ArenaManager();
		return instance;
	}

	public void showFrame() {
		guiFacade.showFrame();
	}

	public void setUser(User user) {
		userController.setUser(user);
	}

	public User getUser() {
		return userController.getUser();
	}

	public void login(String email, String password) {
		if (userController.login(email, password)) {
			updatePanel();
		} else {
			ErrorHandler.getInstance().showError("Couldn't login!");
		}
	}

	public void logout() {
		userController.logout();
		guiFacade.resetMenu();
		guiFacade.startLogin();
	}

	/**
	 * Update the panel by invoking different methods depending on the user type
	 */
	public void updatePanel() {
		if (getUser().getType().matches("Operator")) {
			startOperator();
		} else if (getUser().getType().matches("Advertiser")) {
			startAdvertiser();
		} else if (getUser().getType().matches("LeagueOwner")) {
			startLeagueOwner();
		} else if (getUser().getType().matches("Player")) {
			startPlayer();
		}
	}

	public void startAdvertiser() {
		guiFacade.startAdvertiser();
	}

	public void startLeagueOwner() {
		guiFacade.startLeagueOwner();
	}

	public void startLogin() {
		guiFacade.startLogin();
	}

	public void startOperator() {
		guiFacade.startOperator();
	}

	public void startPlayer() {
		guiFacade.startPlayer();
	}

	public void startSpectator() {
		guiFacade.startSpectator();
	}

	public void startGame(GameModel game) {
		guiFacade.startGame(game);
	}

	public void listGames() {
		guiFacade.listGames();
	}

	public void setPanel(JPanel panel) {
		guiFacade.setPanel(panel);
	}

	public void addAmount(double amount) {
		adController.addAmount(amount);
	}
	
	public double getFounds() {
		return adController.getFounds(getUser());
	}

	public void addMenuItem(JMenu menuItem) {
		guiFacade.addMenuItem(menuItem);
	}

	
	/** Tournaments **/
	public List<ITournament> getTournaments(User user) {
		return leagueController.getTournaments(user);
	}

	public void addTournament(String tournamentName, int numPlayers, String style, Date duration) {
		leagueController.createNewTournament(tournamentName, numPlayers, style, duration);
	}
	
	public void announceTournament() {
		leagueController.announceTournament();
	}
	
	
	/** Advertisements **/
	public List<Ad> getAds() {
		return adController.getAds();
	}

	public void editAd(Ad tmp, int adIndex) {
		adController.editAd(tmp, adIndex);		
	}

	public void addAd(User user, ImageIcon advertise, String description,
			AdvertisementScheme advertisementScheme) {
		adController.addAd(user, advertise, description, advertisementScheme);		
	}

	public void removeAd(int index) {
		adController.removeAd(index);		
	}
	
	public boolean applyForTournament(ITournament tournament) {
		return leagueController.applyForTournament(tournament, getUser());
	}
	
	public void conductTournament(ITournament tournament) {
		leagueController.conductTournament(tournament);
	}
	
	public void archiveTournament(ITournament tournament) {
		leagueController.archiveTournament(tournament);
	}
}
